﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Diagnostics;
using System.ComponentModel;

namespace Mindfor.Web
{
	/// <summary>
	/// Contains information about MVC module, controller and action.
	/// </summary>
	[DebuggerDisplay("{ModuleName} / {ControllerName} / {ActionName}")]
	public class ActionPath
	{
		/// <summary>
		/// Gets or sets pages execution module name. If <c>Null</c> then System is used.
		/// </summary>
		[DisplayName("Модуль")]
		public virtual string ModuleName { get; set; }

		/// <summary>
		/// Gets or sets pages execution controller name. If <c>Null</c> then System is used.
		/// </summary>
		[DisplayName("Controller")]
		public virtual string ControllerName { get; set; }

		/// <summary>
		/// Gets or sets page execution action name. If <c>Null</c> then default Index action is used.
		/// </summary>
		[DisplayName("Action")]
		public virtual string ActionName { get; set; }

		/// <summary>
		/// Initializes new instance.
		/// </summary>
		public ActionPath()
		{
		}

		/// <summary>
		/// Initializes new instance.
		/// </summary>
		/// <param name="moduleName">Page execution controller module name.</param>
		/// <param name="controllerName">Page execution controller name.</param>
		/// <param name="actionName">Page execution controller action name.</param>
		public ActionPath(string moduleName, string controllerName, string actionName)
		{
			ModuleName = moduleName;
			ControllerName = controllerName;
			ActionName = actionName;
		}

		public override string ToString()
		{
			return IsEmpty() ? "" : String.Format("{0} / {1} / {2}", ModuleName, ControllerName, ActionName);
		}

		public override bool Equals(object obj)
		{
			ActionPath ci = obj as ActionPath;
			if (ci == null)
				return false;
			return ModuleName == ci.ModuleName && ControllerName == ci.ControllerName && ActionName == ci.ActionName;
		}

		public static bool operator==(ActionPath c1, ActionPath c2)
		{
			if ((object)c1 == null)
				return (object)c2 == null;
			return c1.Equals(c2);
		}

		public static bool operator!=(ActionPath c1, ActionPath c2)
		{
			return !(c1 == c2);
		}

		/// <summary>
		/// Retruns if action path is not full.
		/// True, if any of ModuleName, ControllerName or ActionName is null or empty.
		/// </summary>
		public bool IsEmpty()
		{
			return String.IsNullOrEmpty(ModuleName) || String.IsNullOrEmpty(ControllerName) || String.IsNullOrEmpty(ActionName);
		}

		/// <summary>
		/// Returns module name.
		/// If module, controller or action name is null then returns system module name.
		/// </summary>
		public string GetModuleNameOrDefault()
		{
			if (IsEmpty())
				return CmsConstants.SystemModuleName;
			return ModuleName;
		}

		/// <summary>
		/// Returns controller name.
		/// If module, controller or action name is null then returns system controller name.
		/// </summary>
		public string GetControllerNameOrDefault()
		{
			if (IsEmpty())
				return CmsConstants.SystemControllerName;
			return ControllerName;
		}

		/// <summary>
		/// Returns action name.
		/// If module, controller or action name is null then returns text page action name.
		/// </summary>
		public string GetActionNameOrDefault()
		{
			if (IsEmpty())
				return CmsConstants.TextPageActionName;
			return ActionName;
		}

		/// <summary>
		/// Returns module for this controller info.
		/// </summary>
		public ModuleBase GetModule()
		{
			return ModuleFactory.Default.Modules[GetModuleNameOrDefault()];
		}

		/// <summary>
		/// Returns controller descriptor for this controller info.
		/// </summary>
		public ControllerDescriptor GetController()
		{
			ModuleBase module = GetModule();
			if (module == null)
				return null;
			return module.GetController(GetControllerNameOrDefault());
		}

		/// <summary>
		/// Returns action descriptors for this controller info.
		/// Returns null if controller not found.
		/// </summary>
		/// <returns></returns>
		public ActionDescriptor[] GetAction()
		{
			ControllerDescriptor controller = GetController();
			if (controller == null)
				return null;
			return controller.GetCanonicalAction(GetActionNameOrDefault());			
		}

		/// <summary>
		/// Returns roles array that are allowed to access controller action. Returns null if action is not found or no CmsAuthorizeAttribute found.
		/// </summary>
		public string[] GetActionAllowRoles()
		{
			ActionDescriptor[] actions = GetAction();
			if (actions != null)
			{
				foreach (ActionDescriptor action in actions)
				{
					CmsAuthorizeAttribute attr = action.GetCmsAuthorizeAttribute();
					if (attr != null)
						return attr.GetAllowRoles();
				}
			}

			return null;
		}
	}
}
